package net.stogi.unicore.beyond.ui.client.taskeditor.propertyeditor;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import net.stogi.common.mvp.core.behavior.Behavior;
import net.stogi.unicore.beyond.api.model.ValueType;

import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.form.Field;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.Widget;

class PropertyEditorWidget extends Widget implements PropertyEditorView {

	private class BooleanValueTypeField implements ValueTypeField {

		private final SimpleComboBox<Boolean> field = new SimpleComboBox<Boolean>();

		public BooleanValueTypeField() {
			field.add(Arrays.asList(true, false));
			// field.setAllowBlank(false);
			field.setFieldLabel("Value");
			field.setForceSelection(true);
		}

		@Override
		public Field<?> asField() {
			return field;
		}

		@Override
		public String getValue() {
			return field.getSelection().get(0).getValue().toString();
		}

		@Override
		public void setValue(String value) {
			boolean convertedValue = false;
			if (value != null) {
				convertedValue = Boolean.parseBoolean(value);
			}
			field.setSimpleValue(convertedValue);
		}
	}

	private class DateValueTypeField implements ValueTypeField {

		private final DateField field = new DateField();
		
		private final DateTimeFormat format = DateTimeFormat.getFullDateTimeFormat();

		public DateValueTypeField() {
			// field.setAllowBlank(false);
			field.setFieldLabel("Value");
			field.getPropertyEditor().setFormat(format);
		}

		@Override
		public Field<?> asField() {
			return field;
		}

		@Override
		public String getValue() {
			String convertedValue = null;
			if (field.getValue() != null) {
				convertedValue = format.format(field.getValue());
			}
			return convertedValue;
		}

		@Override
		public void setValue(String value) {
			Date convertedValue = null;
			if (value != null) {
				convertedValue = format.parse(value);
			}
			field.setValue(convertedValue);
		}
	}

	private class DoubleValueTypeField implements ValueTypeField {

		private final NumberField field = new NumberField();

		public DoubleValueTypeField() {
			// field.setAllowBlank(false);
			field.setFieldLabel("Value");
		}

		@Override
		public Field<?> asField() {
			return field;
		}

		@Override
		public String getValue() {
			String convertedValue = null;
			if (field.getValue() != null) {
				convertedValue = Double.toString(field.getValue().doubleValue());
			}
			return convertedValue;
		}

		@Override
		public void setValue(String value) {
			Double convertedValue = null;
			if (value != null) {
				convertedValue = Double.parseDouble(value);
			}
			field.setValue(convertedValue);
		}
	}

	private class IntegerValueTypeField implements ValueTypeField {

		private final NumberField field = new NumberField();

		public IntegerValueTypeField() {
			// field.setAllowBlank(false);
			field.setAllowDecimals(false);
			field.setFieldLabel("Value");
		}

		@Override
		public Field<?> asField() {
			return field;
		}

		@Override
		public String getValue() {
			String convertedValue = null;
			if (field.getValue() != null) {
				convertedValue = Integer.toString(field.getValue().intValue());
			}
			return convertedValue;
		}

		@Override
		public void setValue(String value) {
			Integer convertedValue = null;
			if (value != null) {
				convertedValue = Integer.parseInt(value);
			}
			field.setValue(convertedValue);
		}
	}

	private class ListValueTypeField implements ValueTypeField {

		private final TextField<String> field = new TextField<String>();

		public ListValueTypeField() {
			// field.setAllowBlank(false);
			field.setFieldLabel("Value");
		}

		@Override
		public Field<?> asField() {
			return field;
		}

		@Override
		public String getValue() {
			return field.getValue();
		}

		@Override
		public void setValue(String value) {
			field.setValue(value);
		}
	}

	private class PropertyEditorWindow extends Window {

		private final Button cancelButton = new Button();

		private final TextField<String> keyTextField = new TextField<String>();

		private final FormPanel mainPanel = new FormPanel();

		private final Button okButton = new Button();

		private ValueTypeField valueTypeField;

		public PropertyEditorWindow(ValueTypeField valueTypeField) {
			this.valueTypeField = valueTypeField;
			initComposite();
			initI18n();
			initLayout();
		}

		public void clear() {
			keyTextField.setValue(null);
			valueTypeField.setValue(null);
		}

		private void initComposite() {
			keyTextField.setEnabled(false);

			mainPanel.setAutoHeight(true);
			mainPanel.setBodyBorder(false);
			mainPanel.setHeaderVisible(false);
			mainPanel.setLabelSeparator("");

			setClosable(false);
			setFrame(true);
			setLayout(new FitLayout());
			setModal(true);
			setResizable(false);
			setWidth("30%");
		}

		private void initI18n() {
			keyTextField.setFieldLabel("Key");
			okButton.setText("Ok");
			cancelButton.setText("Cancel");
			setHeading("Property Editor");
		}

		private void initLayout() {
			mainPanel.add(keyTextField, DEFAULT_FORM_DATA);
			mainPanel.add(valueTypeField.asField(), DEFAULT_FORM_DATA);
			add(mainPanel);
			addButton(okButton);
			addButton(cancelButton);
		}
	}

	private class StringValueTypeField implements ValueTypeField {

		private final TextField<String> field = new TextField<String>();

		public StringValueTypeField() {
			field.setFieldLabel("Value");
		}

		@Override
		public Field<?> asField() {
			return field;
		}

		@Override
		public String getValue() {
			return field.getValue();
		}

		@Override
		public void setValue(String value) {
			field.setValue(value);
		}
	}

	private interface ValueTypeField {

		Field<?> asField();

		String getValue();

		void setValue(String value);
	}

	private static final FormData DEFAULT_FORM_DATA = new FormData("-22");

	private final Map<ValueType, PropertyEditorWindow> windows = new HashMap<ValueType, PropertyEditorWindow>();

	public PropertyEditorWidget() {
		windows.put(ValueType.BOOLEAN, new PropertyEditorWindow(new BooleanValueTypeField()));
		windows.put(ValueType.DATE, new PropertyEditorWindow(new DateValueTypeField()));
		windows.put(ValueType.DOUBLE, new PropertyEditorWindow(new DoubleValueTypeField()));
		windows.put(ValueType.INTEGER, new PropertyEditorWindow(new IntegerValueTypeField()));
		windows.put(ValueType.LIST, new PropertyEditorWindow(new ListValueTypeField()));
		windows.put(ValueType.STRING, new PropertyEditorWindow(new StringValueTypeField()));
	}

	@Override
	public String collectPropertyValue() {
		String value = null;
		for (PropertyEditorWindow window : windows.values()) {
			if (window.isVisible()) {
				value = window.valueTypeField.getValue();
				break;
			}
		}
		return value;
	}

	@Override
	public void disapper() {
		for (PropertyEditorWindow window : windows.values()) {
			if (window.isVisible()) {
				window.hide();
				window.clear();
			}
		}
	}

	@Override
	public void displayProperty(String key, ValueType valueType, String value) {
		windows.get(valueType).keyTextField.setValue(key);
		windows.get(valueType).valueTypeField.setValue(value);
		windows.get(valueType).show();
	}

	@Override
	public void setCancelBehavior(final Behavior behavior) {
		for (PropertyEditorWindow window : windows.values()) {
			window.cancelButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

				@Override
				public void componentSelected(ButtonEvent ce) {
					behavior.behave();
				}
			});
		}
	}

	@Override
	public void setOkBehavior(final Behavior behavior) {
		for (PropertyEditorWindow window : windows.values()) {
			window.okButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

				@Override
				public void componentSelected(ButtonEvent ce) {
					behavior.behave();
				}
			});
		}
	}
}
